Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use neverthrow for exceptions #634

Merged
merged 24 commits into from
Nov 23, 2020
Merged

refactor: use neverthrow for exceptions #634

merged 24 commits into from
Nov 23, 2020

Conversation

tshuli
Copy link
Contributor

@tshuli tshuli commented Nov 15, 2020

Problem

Solution

  • Refactor error throwing to instead return neverthrow err() and ok()

@tshuli
Copy link
Contributor Author

tshuli commented Nov 15, 2020

@karrui continuing from #627 - could I trouble you to take a quick look if the approach is correct? If yes, will continue with the refactoring for getProcessedResponses in encrypt-submissions.server.controller and other functions with exceptions after that

Copy link
Contributor

@karrui karrui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general approach is correct :).

src/app/utils/encryption.ts Outdated Show resolved Hide resolved
@tshuli tshuli force-pushed the refactor/neverthrow branch 2 times, most recently from 1c79d7d to 5f4e920 Compare November 17, 2020 12:32
@tshuli tshuli marked this pull request as ready for review November 17, 2020 23:05
Copy link
Contributor

@karrui karrui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some changes, but as a whole correctly done

)

return next()
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: don't need else, since next is already returned in the block.

req.attachments = mapAttachmentsFromParsedResponses(
req.body.parsedResponses,
)
return next()
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can remove the else block if every branch in the if block returns

delete req.body.responses // Prevent downstream functions from using responses by deleting it
} catch (err) {
return next()
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for the else statement here too

form,
req.body.responses,
)
if (getProcessedResponsesResult.isOk()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: prefer swapping the checks to check for errors, since that is the unusual path.

logger.error({
message: 'Invalid encryption',
meta: {
action: 'validateEncryptSubmission',
...createReqMeta(req),
formId: form._id,
},
error,
error: isEncryptedResult.error,
})
return res
.status(StatusCodes.BAD_REQUEST)
.json({ message: 'Invalid data was found. Please submit again.' })
}

if (req.body.responses) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we swap the checks also? Makes for easier reading of the flow. Get all errors out of the way first, then the final product is a success return:

if (!req.body.responses) {
  return res.sendStatus(StatusCodes.BAD_REQUEST)
}

...
// Continue with code

}

const fieldTypeEither = doFieldTypesMatch(formField, response)

if (isLeft(fieldTypeEither)) {
throw new Error(fieldTypeEither.left)
return err(new ValidateFieldError(fieldTypeEither.left))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment, ignore: Mixing fp-ts and neverthrow makes my brain hurt lol

}
}
return ok(undefined)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return true here also

const testFunc = () => validateField(formId, formField, response)
expect(testFunc).toThrow()
const testFunc = validateField(formId, formField, response)
expect(testFunc.isErr()).toBe(true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should add expect statements to check the unwrapped error

const testFunc = () => validateField(formId, formField, response)
expect(testFunc).not.toThrow()
const testFunc = validateField(formId, formField, response)
expect(testFunc.isOk()).toBe(true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, should check for return value of ok

@@ -34,59 +34,59 @@ describe('Attachment validation', () => {
it('should disallow submission with no attachment if it is required', () => {
const formField = makeField(fieldId, '1')
const response = makeResponse(fieldId, undefined)
const testFunc = () => validateField(formId, formField, response)
expect(testFunc).toThrow()
const testFunc = validateField(formId, formField, response)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename testFunc -> validateResult for all the changed tests. They are not functions anymore haha

@tshuli tshuli force-pushed the refactor/neverthrow branch from 5f4e920 to 6ccc3c1 Compare November 18, 2020 14:02
@tshuli tshuli requested a review from karrui November 18, 2020 14:22
@tshuli
Copy link
Contributor Author

tshuli commented Nov 18, 2020

@karrui thanks for reviewing, made edits for your re-review :)

Copy link
Contributor

@karrui karrui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

const moreAnswersTestFunc = () =>
validateField(formId, formField, moreAnswers)
expect(moreAnswersTestFunc).toThrow()
const moreAnswersTestFunc = validateField(formId, formField, moreAnswers)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missed a rename from func to result here :P

@tshuli tshuli force-pushed the refactor/neverthrow branch from ea254ae to 9e21a7d Compare November 23, 2020 04:58
@tshuli tshuli merged commit bd77a22 into develop Nov 23, 2020
@tshuli tshuli deleted the refactor/neverthrow branch November 23, 2020 05:30
@mantariksh mantariksh mentioned this pull request Nov 24, 2020
@@ -3,6 +3,8 @@ import EmailValidator from 'src/app/utils/field-validation/validators/EmailValid
import { BasicField } from 'src/types/field/fieldTypes'
import { ISingleAnswerResponse } from 'src/types/response'

import { ValidateFieldError } from '../../../../../dist/backend/app/modules/submission/submission.errors'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:( missed this buggy import here when I reviewed, only discovered when I tried to split out the tests in #742 haha. please dont import from dist in TypeScript tests!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok got it, thanks for letting me know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants